/* eslint-disable @typescript-eslint/indent */
import * as File from './file'
import { AKDict, APIResult, success, fail } from './types'
import { Router } from 'express'
import { parserOptions } from '.pnpm/@vue+compiler-dom@3.2.26/node_modules/@vue/compiler-dom'

const router = Router()

router.get('/characterList/*', (req, res) => {
    const lang = req.params[0] || 'zh_CN'
    const chtable = File.getExcel('character_table', lang)
    if (chtable) {
        const ret: AKDict<any> = {}
        Object.keys(chtable).forEach(id => {
            ret[id] = { charId: id } as any
            ['name', 'itemObtainApproach', 'rarity', 'profession', 'subProfessionId'].forEach(k => {
                ret[id][k] = chtable[id][k] 
            })
        })
        res.send(success(ret))
    } else {
        res.send(fail("Invalid language."))
    }
})

// looks like lodash pick()?
function pick(obj: any, keys: string[]): any {
    return keys.reduce((ret: any, k: string) => (ret[k] = obj[k], ret), {})
}

router.get('/character/:lang/:charId', (req, res) => {
    const _ = req.params
    const lang = (_.lang == '_' ? 'zh_CN' : _.lang)
    const charTable = File.getExcel('character_table', lang)
    const skillTable = File.getExcel('skill_table', lang)
    const equipTable = File.getExcel('uniequip_table', lang)
    const optionTable = File.getCustom('dps_options')
    //const animTable = File.getCustom('dps_anim')

    if (charTable && skillTable && optionTable && equipTable) {
        const charData = charTable[_.charId]
        if (charData) {
            // skill
            const skillData = pick(skillTable, charData.skills.map((x: any) => x.skillId))
            
            const equipData = pick(equipTable.equipDict, equipTable.charEquip[_.charId] || [])
            // options
            const options = ['buff', ...(optionTable.char[_.charId] || [])].map(key => {
                const ret = {...optionTable.tags[key]}
                ret.key = key
                if (key == 'cond' && optionTable.cond_info[_.charId]) {
                    const info = optionTable.cond_info[_.charId]
                    if (!isNaN(info)) {
                        ret.displaytext = `触发天赋#${info} - ${charData.talents[info-1].candidates[0].name}`
                    } else if (info == 'trait') {
                        ret.displaytext = `触发特性`
                    } else {
                        ret.displaytext = info.text
                        ret.explain = info.tooltip
                    }
                }
                return ret
            })
            // anim: keys starts with charId, values in animTable
           // const animData = pick(animTable, 
           //                       Object.keys(animTable).filter(key => key.startsWith(_.charId)))

            res.send(success({
                charData,
                skillData,
                equipData,
                options
            }))
        } else {
            res.send(fail('Invalid charId.'))
        }
    } else {
        res.send(fail('Invalid language.'))
    }
})

router.get('/enemyList/*', (req, res) => {
    const lang = req.params[0] || 'zh_CN'
    const enemyTable = File.getLevels('enemydata/enemy_database', lang)
    if (enemyTable) {
        const ret = enemyTable.enemies.map(item => ({
           enemyId: item.Key,
           name: item.Value[0].enemyData.name.m_value,
           levels: item.Value.length 
        }))
        res.send(success(ret))
    } else {
        res.send(fail('Invalid language.'))
    }
})

interface AKRawAttribute {
    m_defined: boolean
    m_value: number | string
}

interface AKRawBlackboard {
    key: string
    value: number
    valueStr: string | null
}
 
const hasProps = (obj: any, props: string[]) => (
    obj && props.filter(x => obj.hasOwnProperty(x)).length == props.length
) 
const getAttr = (x: AKRawAttribute) => (x.m_defined ? x.m_value : null)
const getBlackboard = (arr: AKRawBlackboard[] | null) => {
    const ret = {} as AKDict<number | string>
    if (arr) {
        //console.log(arr)
        arr.forEach(item => {
            const v = item.valueStr || item.value
            if (v) ret[item.key] = v
        })
        return ret
    } else return null
}

const parseEnemy = (e: any) => {
    const f = JSON.parse(JSON.stringify(e))
    const ret = { level: f.level, ...f.enemyData }
    Object.keys(ret).forEach(k => {
        const v = {} as any
        switch (k) {
            case 'attributes':
                Object.keys(ret[k]).forEach(attrKey => {
                    const att = getAttr(ret[k][attrKey])
                    if (att != null) v[attrKey] = att
                })
                ret[k] = v
                break
            case 'talentBlackboard':
                ret[k] = getBlackboard(ret[k])
                break
            case 'skills':
                if (ret[k]) {
                    ret[k].forEach(sk => {
                        sk.blackboard = getBlackboard(sk.blackboard)
                        v[sk.prefabKey] = sk
                    })
                    ret[k] = v
                }
                break
            default:
                ret[k] = hasProps(ret[k], ['m_defined', 'm_value']) ?
                             getAttr(ret[k]) : ret[k]
        }
    })
    return ret
}

router.get('/enemy/:lang/:enemyId', (req, res) => {
    const _ = req.params
    const lang = (_.lang == '_' ? 'zh_CN' : _.lang)
    const enemyTable = File.getLevels('enemydata/enemy_database', lang)
    if (enemyTable) {
        const enemy = enemyTable.enemies.filter(x => x.Key == _.enemyId)[0]
        if (enemy) {
            res.send(success(enemy.Value.map(parseEnemy)))
        } else {
            res.send(fail('No such enemyId.'))
        }
    } else {
        res.send(fail('Invalid language.'))
    }
})

export default router
